--[[

   Copyright (C) 2007 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

   Written by Charles Cahoon during Summer of Code 2007
--]]

assert(proxy.PROXY_VERSION >= 0x00600, "you need at least mysql-proxy 0.6.0 to run this module")

require("macro_util")
require("log_util")

----------------------
-- Global Variables --
----------------------

proxy.global["verbose"] = os.getenv("MTC_VERBOSE")
if proxy.global["toggle_errors"] == nil then
	proxy.global["toggle_errors"] = false
end
if proxy.global["start_testing"] == nil then
	proxy.global["start_testing"] = false
end
if proxy.global["logs"] == nil then
	proxy.global["logs"] = log_util
end
if proxy.global["macros"] == nil then
	proxy.global["macros"] = macro_util
	proxy.global["macros"].create(proxy, proxy.global["logs"])
end	
local query_packet
local query_num = -1
local query_table

-----------------
-- Proxy Hooks --
-----------------
		
--intercepts client query
--
function read_query( packet )	
	query_packet = packet
	if string.byte(query_packet) == proxy.COM_QUERY then
		query_packet = proxy.global["macros"].parse_command(query_packet)
		if query_packet ~= nil then
			local tmp_packet = ''
			if proxy.global['looping'] == true
			then
				tmp_packet = query_packet:gsub('$N', 1)
				tmp_packet = tmp_packet:gsub( '$' .. proxy.global['loop_counter_name'], 1)
				proxy.queries:append(2, tmp_packet)
			else
				proxy.queries:append(2, query_packet)
			end
			if proxy.global["start_testing"] == true then

				if proxy.global['looping'] == true
				then
					proxy.global["logs"].write_to_test(string.sub(tmp_packet, 2) .. 
						";", proxy.connection.server.thread_id)				
				else
					proxy.global["logs"].write_to_test(string.sub(query_packet, 2) .. 
						";", proxy.connection.server.thread_id)				
				end
			end			
			return proxy.PROXY_SEND_QUERY
		elseif query_packet == nil then
			if proxy.response.type ~= nil then
				return proxy.PROXY_SEND_RESULT
			elseif proxy.global["execute_loop"] == true then
				query_table = {}
				query_num = 3
				for i=1,proxy.global["total_loop_count"] - 1 do
					query_packet = proxy.global["total_loop"][i]
					query_packet = query_packet:gsub('$N', i + 1  )
				    query_packet = query_packet:gsub( '$' .. proxy.global['loop_counter_name'], i + 1)
					proxy.queries:append(query_num, query_packet)
					query_table[query_num] = query_packet
					query_num = query_num + 1					
				end				
				return PROXY_SEND_QUERY				
			end
		end
	end		
end

--intercept server response
--
function read_query_result ( inj )	
	
	if inj.id == 1 and proxy.global["total_loop_count"] > 1 then
		return proxy.PROXY_IGNORE_RESULT
	elseif inj.id == 1 and proxy.global["total_loop_count"] == 1 then
		proxy.response.type = proxy.MYSQLD_PACKET_OK
        proxy.response.resultset = {
        	fields = {
                        {type = proxy.MYSQL_TYPE_STRING, name = "TEST CREATOR"},
                },
                rows = {
                        {"Executed " .. proxy.global["num_queries"] .. " queries X " .. proxy.global["iterations"] .. " times"}
        		}
        }
        proxy.global["execute_loop"] = false
        query_num = -1
        return proxy.PROXY_SEND_RESULT	
	end	
	local res = assert(inj.resultset)
	if proxy.global["execute_loop"] == true then
		proxy.global["logs"].write_to_result(string.sub(query_table[inj.id], 2) .. ";")
	elseif proxy.global["start_testing"] == true then
		proxy.global["logs"].write_to_result(string.sub(query_packet, 2) .. ";")
	end
	if(proxy.global["start_testing"] == true) then
		--CATCH ERROR FROM SERVER
		if res.query_status and (res.query_status < 0 ) then
			if proxy.global["toggle_errors"] == false then
				local i = 0
				local j = 0
			   	local error_code = res.raw:byte(2) + (res.raw:byte(3) * 256)
		     	local sql_state = string.format("%q", res.raw:sub(5, 9))
		     	i, j, sql_state = string.find(sql_state, "^%s*\"([^\"]*)\"", j+1)
			   	local error_msg = string.format("%q", res.raw:sub(10))
			   	i = 0
			   	j = 0
			   	i, j, error_msg = string.find(error_msg, "^%s*\"([^\"]*)\"", j+1)
			   	proxy.global["logs"].write_error(error_code)
			    proxy.global["logs"].write_to_result("ERROR " .. sql_state .. ": " .. error_msg)		    	
			else
				proxy.global["logs"].remove_last_query()
			end
		end
		--SUCCESSFUL RESPONSE FROM SERVER
   		local row_count = 0
		local field_count = 0
		local first = true
		local fields = inj.resultset.fields
		if fields ~= nil then
			local field_string = ""
		  	while fields[field_count] do		  		
	  			local field = fields[field_count]	  			
	  			if field ~= nil then
	  				if first == true then
	  					field_string = field.name
	    				first = false
    				else
    					field_string = field_string .. "\t" .. field.name
    				end        		        		      
	       		end	
		    	field_count = field_count + 1
		  	end	
		  		proxy.global["logs"].write_to_result(field_string, -1)	  
	  		for row in inj.resultset.rows do
		    	local cols = {}
		    	local o = nil
		    	for i = 1, field_count do
		     		if not o then
		        		o = ""
		      		else 
		        		o = o .. "\t"
	    			end
	     			if not row[i] then
		        		o = o .. ""
		      		else
		        		o = o .. row[i]
	        		end
		   		end
		    	if(o ~= nil) then
		    		proxy.global["logs"].write_to_result(o)	  					    			    		
		   		end
		    	row_count = row_count + 1
		  	end		  	
	  	end		
	end
	local row_count = 0 	
	
	--SCRIPT DEBUG OUTPUT
  	if proxy.global["verbose"] == "1" or proxy.global["verbose"] == "2" then
	  	local num_cols = string.byte(res.raw, 1)
	   	if num_cols > 0 and num_cols < 255 then
	     		for row in inj.resultset.rows do
	       			row_count = row_count + 1
	     		end
	   	end
	   	local error_status =""
	   	if res.query_status and (res.query_status < 0 ) then
	       		error_status = "[ERR]"
	   	end   	
	   	if (res.affected_rows) then
	       		row_count = res.affected_rows
	   	end	
	   	if proxy.global["execute_loop"] then
	   		query_packet = query_table[inj.id]
	   	end
	   	print( string.format("%s %6d -- %s {%d} %s",
	     		os.date('%Y-%m-%d %H:%M:%S'),
	    	 	proxy.connection.server.thread_id,
	    	 	string.sub(query_packet, 2),--query,
	     		row_count,
	     		error_status))	
 	end 
 	
 	if inj.id > 2 and inj.id < query_num - 1 then
 		return proxy.PROXY_IGNORE_RESULT
 	end 
 	if inj.id == query_num - 1 then
 		proxy.response.type = proxy.MYSQLD_PACKET_OK
        proxy.response.resultset = {
        	fields = {
                        {type = proxy.MYSQL_TYPE_STRING, name = "TEST CREATOR"},
                },
                rows = {
                        {"Executed " .. proxy.global["num_queries"] .. " queries X " .. proxy.global["iterations"] .. " times"}
        		}
        }
        query_num = -1
        proxy.global["execute_loop"] = false
        return proxy.PROXY_SEND_RESULT
 	end	
end 
 
